/* 
 *	Copyright (C) 2009-2010 miaohua
 *	http://code.google.com/p/lrcshower/
 *
 *  This Program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2, or (at your option)
 *  any later version.
 *   
 *  This Program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 *  GNU General Public License for more details.
 *   
 *  You should have received a copy of the GNU General Public License
 *  along with GNU Make; see the file COPYING.  If not, write to
 *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
 *  http://www.gnu.org/copyleft/gpl.html
 *
 */

#include "Stdafx.h"
#include <streams.h>     
#include <initguid.h>
#include <string>
#include "TypeDef.h"
#include "LrcShowFilterPins.h"           // The input & output pins
#include "FilterSetting.h"               // Filter's gobal property setting
#include "CLrcShowFilter.h"              // Filter header file
#include "LrcShowFilterUUID.h"           // Our own public guids
#include "LrcShowFilterWinProp.h"        // Lrc window show mode Property sheet implementation class
#include "LrcOnLineSearchProp.h"         // Lrc onnline search Property sheet implementation class
#include "LrcShowFilterDesktopProp.h"    // Lrc desktop show mode Property sheet implementation class
using namespace std;


// Filter's gobal property setting
FilterSetting Gbl_Setting;

// DbgPrinter macro definition
//
// Put out the name of the function and instance on the debugger.
#define DbgPrinter(Opt, Str) DbgLog(( Opt\
                          , 2\
                          , TEXT("CLrcShowFilter(Instance %d)::%s\0") \
                          , m_nThisInstance\
                          , TEXT(Str)\
                         ));

//
// Setup data
//
const AMOVIESETUP_MEDIATYPE
sudPinTypes =   { &MEDIATYPE_NULL                // MajorType(we can accept any media type)
                , &MEDIASUBTYPE_NULL }  ;        // MinorType

const AMOVIESETUP_PIN
psudPins[] = { { L"Input"                        // strName
               , FALSE                           // bRendered
               , FALSE                           // bOutput
               , FALSE                           // bZero
               , FALSE                           // bMany
               , &CLSID_NULL                     // clsConnectsToFilter
               , L"Output"                       // strConnectsToPin
               , 1                               // nTypes
               , &sudPinTypes }                  // lpTypes(any media type can be input)
             , { L"Output"                       // the same with input pin's parameter
               , FALSE                           
               , TRUE                           
               , FALSE           
               , FALSE                 
               , &CLSID_NULL    
               , L"Input"     
               , 1                   
               , &sudPinTypes } };    


const AMOVIESETUP_FILTER
LrcFilter = { &CLSID_LrcShowFilter                // UUID of lrc show filter
            , L"LrcShowFilter"                    // Name
            , MERIT_DO_NOT_USE                    // not used by system automatically
            , 2                                   // two pins
            , psudPins };                         // pin array


// Needed for the CreateInstance mechanism
CFactoryTemplate g_Templates[]=
    {   {L"LrcShowFilter"
        , &CLSID_LrcShowFilter
        , CLrcShowFilter::CreateInstance
        , NULL
        , &LrcFilter }
    ,
        { L"LrcShowFilter Window Property Page"
        , &CLSID_LrcShowFilterWinSettingPage
        , CLrcShowFilterWinProperties::CreateInstance }
    ,
        { L"LrcShowFilter Desktop Property Page"
        , &CLSID_LrcShowFilterDesktopSettingPage
        , CLrcShowFilterDesktopProperties::CreateInstance }
    ,
        { L"LrcOnLineSearch Property Page"
        , &CLSID_LrcOnLineSearchSettingPage
        , CLrcOnLineSearchProperties::CreateInstance }
    };

int g_cTemplates = sizeof(g_Templates)/sizeof(g_Templates[0]);

//
// initialise the static instance count.
//
int CLrcShowFilter::m_nInstanceCount = 0;



// ----------------------------------------------------------------------------
//            Lrc Show Filter implementation
// ----------------------------------------------------------------------------

// CLrcShowFilter::Constructor
CLrcShowFilter::CLrcShowFilter(TCHAR *tszName, LPUNKNOWN punk, HRESULT *phr)
    : CTransInPlaceFilter (tszName, punk, CLSID_LrcShowFilter, phr)
{
     m_nThisInstance = ++m_nInstanceCount;
     m_mtPreferred.InitMediaType () ;

     // Output the creation information on the debugger
     DbgPrinter(LOG_TRACE, "CLrcShowFilter");

     // Set the time offset to be zero
     m_Offset = 0;

     // Defualt lrc show mode is window mode
     m_ShowMode = false;
}

// CreateInstance
//
// Override CClassFactory method.
// Provide the way for COM to create a CLrcShowFilter object
CUnknown * WINAPI CLrcShowFilter::CreateInstance(LPUNKNOWN punk, HRESULT *phr) 
{
     ASSERT(phr);

     CLrcShowFilter *pNewObject = new(nothrow) CLrcShowFilter(NAME("LrcShow Filter"), punk, phr );
     if( pNewObject == NULL ) 
     {
        if(phr)
           *phr = E_OUTOFMEMORY;
     }

     return pNewObject;
}

// The main function, here we get the time stamp and synchronize the lrc with progress of song
HRESULT CLrcShowFilter::Transform(IMediaSample *pSample)
{ 
     UNREFERENCED_PARAMETER(pSample); 

     long long Now = 0;

     //Get the filter graph reference clock 
     //Make sure this step must be successful
     IReferenceClock * RefClock = NULL;
     this->GetSyncSource(&RefClock);
     if( RefClock )
     {
         RefClock->GetTime(&Now);
         RefClock->Release();
     } else
	     DbgPrinter(LOG_ERROR, "Can't get reference clock!");

     long long Start = m_tStart/10000;
     Now /= 10000;

     // Do the state judgement here to prevent from scrol the lrc when filter is paused and stopped
     if( m_State == State_Running )
     {
         if( m_ShowMode )
             m_DesktopShower.DoOnTimeScrollJob(Now-Start+m_Offset);
         else
             m_WinShower.DoOnTimeScrollJob(Now-Start+m_Offset);
     }
     return NOERROR; 
}

// When the filter stops, we must stop our lrc show scroller(show start of lrc)
STDMETHODIMP CLrcShowFilter::Stop()
{
     if( m_ShowMode )
         m_DesktopShower.Reset();
     else
         m_WinShower.Reset();

     return __super::Stop();
}

// GetPin
//
// Override CBaseFilter method.
// Return a non-addrefed CBasePin * for the user to addref if he holds onto it
// for longer than his pointer to us.  This is part of the implementation of
// EnumMediaTypes.  All attempts to refer to our pins from the outside have
// to come through here, so it's a valid place to create them.
CBasePin *CLrcShowFilter::GetPin(int n)
{
     //Create the single input pin and the single output pin
     //If anything fails, clean up all
     if( m_pInput == NULL || m_pOutput == NULL ) 
     {
         HRESULT hr = S_OK;

         m_pInput = new CLrcShowFilterInputPin(NAME("LrcShowFilter input pin"),
                                           this,              // Owner filter
                                           &hr,               // Result code
                                           L"Input");         // Pin name

         // A failed return code should delete the object
         if( FAILED(hr) || m_pInput == NULL ) 
         {
             delete m_pInput;
             m_pInput = NULL;
             return NULL;
         }

         m_pOutput = new CLrcShowFilterOutputPin(NAME("LrcShowFilter output pin"),
                                            this,            // Owner filter
                                            &hr,             // Result code
                                            L"Output");      // Pin name

         // Failed return codes cause both objects to be deleted
         if( FAILED(hr) || m_pOutput == NULL ) 
         {
             delete m_pInput;
             m_pInput = NULL;

             delete m_pOutput;
             m_pOutput = NULL;
             return NULL;
         }
     }

     /* Find which pin is required */
     switch(n) 
     {
        case 0:
             return m_pInput;
        case 1:
             return m_pOutput;
     }

     return NULL;

}


// NonDelegatingQueryInterface
//
// Override CUnknown method.
// Part of the basic COM (Compound Object Model) mechanism.
// This is how we expose our interfaces.
STDMETHODIMP CLrcShowFilter::NonDelegatingQueryInterface(REFIID riid, void **ppv)
{
     CheckPointer(ppv,E_POINTER);

     if( riid == IID_ILrcShowFilter )
         return GetInterface((ILrcShowFilter *) this, ppv);
     else if( riid == IID_ISpecifyPropertyPages )
         return GetInterface((ISpecifyPropertyPages *) this, ppv);
     else
         return CTransformFilter::NonDelegatingQueryInterface(riid, ppv);
}


// get_IPin
//
// ILrcShowFilter method.
// Set *ppPin to the upstream output pin which supplies us
// or to NULL if there is no upstream pin connected to us.
STDMETHODIMP CLrcShowFilter::get_IPin (IPin **ppPin)
{
     CheckPointer(ppPin,E_POINTER);
     CAutoLock locker(&m_FilterLock);

     if( !m_pInput )
     {
         *ppPin = NULL;
         return NOERROR;
     }

     if( !m_pInput->IsConnected() )
     {
         *ppPin = NULL;
     } else {
         *ppPin = m_pInput->GetConnected (); // Return upstream filter's output pin
         (*ppPin)->AddRef();
     }

     return NOERROR;
}


// put_MediaType
//
// ILrcShowFilter method.
STDMETHODIMP CLrcShowFilter::put_MediaType(CMediaType *pmt)
{
     CheckPointer(pmt,E_POINTER);
     CAutoLock locker(&m_FilterLock);

     //If the state of the graph is running, fail the call.
     if( m_State == State_Running )
         return E_UNEXPECTED;

     //Check the source and sink filters like this media type
     if( pmt == NULL )
     {
         m_mtPreferred.InitMediaType();
     } else {
         IPin *pPin= m_pInput->GetConnected();
         if( pPin ) 
         {
             if( pPin->QueryAccept(pmt) != NOERROR ) 
             {
                 MessageBox(NULL,TEXT("Upstream filter cannot provide this type"),
                            TEXT("Format Selection"),
                            MB_OK | MB_ICONEXCLAMATION);
                 return VFW_E_TYPE_NOT_ACCEPTED;
             }
         }

         pPin= m_pOutput->GetConnected();
         if( pPin ) 
         {
             if( pPin->QueryAccept(pmt) != NOERROR ) 
             {
                 MessageBox(NULL,TEXT("Downstream filter cannot accept this type"),
                            TEXT("Format Selection"),
                            MB_OK | MB_ICONEXCLAMATION);
                 return VFW_E_TYPE_NOT_ACCEPTED;
             }
         }

         m_mtPreferred = *pmt ;
     }

     //
     // force reconnect of input if the media type of connection does not match.
     //
     if( m_pInput->IsConnected() )
     {
         if( m_pInput->CurrentMediaType()!= m_mtPreferred )
             m_pGraph->Reconnect(m_pInput);
     }

     return NOERROR;
}


// get_MediaType
//
// ILrcShowFilter method.
// Set *pmt to the current preferred media type.
STDMETHODIMP CLrcShowFilter::get_MediaType(CMediaType **pmt)
{
     CheckPointer(pmt,E_POINTER);
     CAutoLock locker(&m_FilterLock);

     *pmt = &m_mtPreferred;
     return NOERROR;
} 


// get_State
//
// ILrcShowFilter method
// Set *state to the current state of the filter (State_Stopped etc)
STDMETHODIMP CLrcShowFilter::get_State(FILTER_STATE *pState)
{
     CheckPointer(pState,E_POINTER);
     CAutoLock locker(&m_FilterLock);

     *pState = m_State;
     return NOERROR;
} 


// SetWinAlignmentOpt
//
// ILrcShowFilter method
// Set alignment(center, left, right) for window lrc show
STDMETHODIMP CLrcShowFilter::SetWinAlignmentOpt(int Option)
{
     ASSERT(Option >= 0 && Option <= 2);
     CAutoLock locker(&m_FilterLock);

     m_WinShower.ChangeAlign(Option);
     return NOERROR;
}


// SetWinLineInterval
//
// ILrcShowFilter method
// Set lrc line's vertical interval for lrc show(the unit is pixel)
STDMETHODIMP CLrcShowFilter::SetWinLineInterval(int Interval)
{
     CAutoLock locker(&m_FilterLock);

     m_WinShower.ChangeLineInterval(Interval);
     return NOERROR;
}


// SetWinKaraokeMode
//
// ILrcShowFilter method
// Set karaoke mode for lrc show
STDMETHODIMP CLrcShowFilter::SetWinKaraokeMode(bool Mode)
{
     CAutoLock locker(&m_FilterLock);

     m_WinShower.ChangeKaraokeMode(Mode);
     return NOERROR;
}

// SetWinGradientMode
//
// ILrcShowFilter method
// Set gradient mode for window lrc show
STDMETHODIMP CLrcShowFilter::SetWinGradientMode(bool Mode)
{
     CAutoLock locker(&m_FilterLock);

     m_WinShower.ChangeGradientMode(Mode);
     return NOERROR;
}


// SetWinAutoResizeMode
//
// ILrcShowFilter method
// Set auto resize mode for window lrc show
STDMETHODIMP CLrcShowFilter::SetWinAutoResizeMode(bool Mode)
{
     CAutoLock locker(&m_FilterLock);

     m_WinShower.SetAutoResizeMode(Mode);
     return NOERROR;
}


// SetWinTopMostMode
//
// ILrcShowFilter method
// Set topmost mode for window lrc show
STDMETHODIMP CLrcShowFilter::SetWinTopMostMode(bool Mode)
{
     CAutoLock locker(&m_FilterLock);

     m_WinShower.SetTopMostMode(Mode);
     return NOERROR;
}

// SetWinFont
//
// ILrcShowFilter method
// Set font style for lrc window show
STDMETHODIMP CLrcShowFilter::SetWinFont(const LOGFONT* font)
{
     CAutoLock locker(&m_FilterLock);

     m_WinShower.ChangeFont(font);
     return NOERROR;
}


// SetWinBgClr
//
// ILrcShowFilter method
// Set the background color for window lrc show
STDMETHODIMP CLrcShowFilter::SetWinBgClr(COLORREF Clr)
{
     CAutoLock locker(&m_FilterLock);

     m_WinShower.ChangeBgClr(Clr);
     return NOERROR;
}
        

// SetWinFocusClr
//
// ILrcShowFilter method
// Set the color for the current foucus line in window lrc show
STDMETHODIMP CLrcShowFilter::SetWinFocusClr(COLORREF Clr)
{
     CAutoLock locker(&m_FilterLock);

     m_WinShower.ChangeFocusLineClr(Clr);
     return NOERROR;
}


// SetWinUnFocusClr
//
// ILrcShowFilter method
// Set the color for the other line in window lrc show
STDMETHODIMP CLrcShowFilter::SetWinUnFocusClr(COLORREF Clr)
{
     CAutoLock locker(&m_FilterLock);

     m_WinShower.ChangeOtherLineClr(Clr);
     return NOERROR;
}

// SetWinShowWnd
//
// ILrcShowFilter method
// Set the lrc show window's handler for window lrc show
STDMETHODIMP CLrcShowFilter::SetWinShowWnd(HWND Handler)
{
     CAutoLock locker(&m_FilterLock);

     if( Handler )
     {
         // Set window's handler
	     m_WinShower.ChangeShowWnd(Handler);
     }

     return NOERROR;
} 


// SetWinLrcFile
//
// ILrcShowFilter method
// Set lrc file's full path for window lrc show
STDMETHODIMP CLrcShowFilter::SetWinLrcFile(const TCHAR * FullPath)
{
     CAutoLock locker(&m_FilterLock);

     LoadWinLrcFileHelper(FullPath, false);

     return NOERROR;
}


// SetDuration
//
// ILrcShowFilter method
// Set lrc file's full path
STDMETHODIMP CLrcShowFilter::SetDuration(long long Duration)
{
     CAutoLock locker(&m_FilterLock);

     // Set the media file's duration outside of the filter                          
     m_LrcParser.SetDuration(Duration);

     return NOERROR;
}

// StartWinShow
//
// ILrcShowFilter method
// Start the show lrc in window mode
STDMETHODIMP CLrcShowFilter::StartWinShow()
{
     CAutoLock locker(&m_FilterLock);

     if( !m_WinShower.Start() )
	     return E_FAIL;

     return NOERROR;
}

// StopWinShow
//
// ILrcShowFilter method
// Stop the show lrc in window mode
STDMETHODIMP CLrcShowFilter::StopWinShow()
{
     CAutoLock locker(&m_FilterLock);

     m_WinShower.Stop();
     return NOERROR;
}


// StartDesktopShow
//
// ILrcShowFilter method
// Start the show lrc in desktop mode
STDMETHODIMP CLrcShowFilter::StartDesktopShow()
{
     CAutoLock locker(&m_FilterLock);

     if( !m_DesktopShower.Start() )
	     return E_FAIL;

     return NOERROR;
}

// StopDesktopShow
//
// ILrcShowFilter method
// Stop the show lrc in desktop mode
STDMETHODIMP CLrcShowFilter::StopDesktopShow()
{
     CAutoLock locker(&m_FilterLock);

     m_DesktopShower.Stop();

     return NOERROR;
}

// SetDeskShowWnd
//
// ILrcShowFilter method
// Set showing window handler for desktop lrc show
STDMETHODIMP CLrcShowFilter::SetDeskShowWnd(HWND Handler)
{
     CAutoLock locker(&m_FilterLock);

     m_DesktopShower.ChangeShowWnd(Handler);
     return NOERROR;
}

// SetDeskKaraokeMode
//
// ILrcShowFilter method
// Set karaoke mode for lrc show
STDMETHODIMP CLrcShowFilter::SetDeskKaraokeMode(bool Mode)
{
     CAutoLock locker(&m_FilterLock);

     m_DesktopShower.ChangeKaraokeMode(Mode);
     return NOERROR;
}

// SetDeskShadowMode
//
// ILrcShowFilter method
// Set shadow mode for lrc show
STDMETHODIMP CLrcShowFilter::SetDeskShadowMode(bool Mode)
{
     CAutoLock locker(&m_FilterLock);

     m_DesktopShower.ChangeShadowMode(Mode);
     return NOERROR;
}

// SetDeskOutlineMode
//
// ILrcShowFilter method
// Set outline mode for lrc show
STDMETHODIMP CLrcShowFilter::SetDeskOutlineMode(bool Mode)
{
     CAutoLock locker(&m_FilterLock);

     m_DesktopShower.ChangeOutlineMode(Mode);
     return NOERROR;
}

// SetDeskTopMostMode
//
// ILrcShowFilter method
// Set topmost mode for lrc show
STDMETHODIMP CLrcShowFilter::SetDeskTopMostMode(bool Mode)
{
     CAutoLock locker(&m_FilterLock);

     m_DesktopShower.ChangeTopMostMode(Mode);
     return NOERROR;
}


// SetDeskFont
//
// ILrcShowFilter method
// Set font style for lrc show
STDMETHODIMP CLrcShowFilter::SetDeskFont(const LOGFONT* font)
{
     CAutoLock locker(&m_FilterLock);

     m_DesktopShower.ChangeFont(font);
     return NOERROR;
}


// SetDeskBgClr
//
// ILrcShowFilter method
// Set the background color for lrc show
STDMETHODIMP CLrcShowFilter::SetDeskBgClr(COLORREF Clr)
{
     CAutoLock locker(&m_FilterLock);

     m_DesktopShower.ChangeBgClr(Clr);
     return NOERROR;
}
  
// SetDeskLrcFile
//
// ILrcShowFilter method
// Set desktop lrc file's full path
STDMETHODIMP CLrcShowFilter::SetDeskLrcFile(const TCHAR * FullPath)
{
     CAutoLock locker(&m_FilterLock);

     LoadDeskLrcFileHelper(FullPath, false);

     return NOERROR;
}

// SetDeskBgTransparent
//
// ILrcShowFilter method
// Set the background transparent for desktop lrc show mode
STDMETHODIMP CLrcShowFilter::SetDeskBgTransparent(BYTE Transparent)
{
     CAutoLock locker(&m_FilterLock);

     m_DesktopShower.ChangeBgTransparent(Transparent);
     return NOERROR;
}
 

// SetDeskBgTransparent
//
// ILrcShowFilter method
// Set lrc transparent for desktop lrc show mode
STDMETHODIMP CLrcShowFilter::SetDeskLrcTransparent(BYTE Transparent)
{
     CAutoLock locker(&m_FilterLock);

     m_DesktopShower.ChangeLrcTransparent(Transparent);
     return NOERROR;
}

// SetDeskFocusClr
//
// ILrcShowFilter method
// Set focus part color for desktop lrc show mode
STDMETHODIMP CLrcShowFilter::SetDeskFocusClr(COLORREF Upper, COLORREF Mid, COLORREF Lower)
{
     CAutoLock locker(&m_FilterLock);

     m_DesktopShower.ChangeFocusLineClr(Upper, Mid, Lower);
     return NOERROR;
}

// SetDeskUnFocusClr
//
// ILrcShowFilter method
// Set unfocus part color for desktop lrc show mode
STDMETHODIMP CLrcShowFilter::SetDeskUnFocusClr(COLORREF Upper, COLORREF Mid, COLORREF Lower)
{
     CAutoLock locker(&m_FilterLock);

     m_DesktopShower.ChangeUnFocusLineClr(Upper, Mid, Lower);
     return NOERROR;
}

// SetDeskTransMode
//
// ILrcShowFilter method
// Set transparence for desktop lrc show widnow
STDMETHODIMP CLrcShowFilter::SetDeskTransMode(bool Mode)
{
     CAutoLock locker(&m_FilterLock);

     m_DesktopShower.ChangeWinTransMode(Mode);
     return NOERROR;
}

// ChgToDeskShow
//
// ILrcShowFilter method
// Set lrc show mode to desktop mode
STDMETHODIMP CLrcShowFilter::ChgToDeskShow()
{
     CAutoLock locker(&m_FilterLock);
   
     // Do change
     m_WinShower.Stop();
     m_DesktopShower.Start();
     
     // Set show mode to desktop mode
     m_ShowMode = true;
     
     return NOERROR;
}

// ChgToWinShow
//
// ILrcShowFilter method
// Set lrc show mode to window mode 
STDMETHODIMP CLrcShowFilter::ChgToWinShow()
{
     CAutoLock locker(&m_FilterLock);
      
     // Do change
     m_DesktopShower.Stop();
     m_WinShower.Start();

     // Set change mode to window mode
     m_ShowMode = false;

     return NOERROR;
}

// SetShowMode
//
// ILrcShowFilter method
// Set lrc show mode to window mode or desktop mode
STDMETHODIMP CLrcShowFilter::SetShowMode(bool Mode)
{
     CAutoLock locker(&m_FilterLock);
     
     // Set show mode(0 : window mode; 1 : desktop mode)
     m_ShowMode = Mode;
    
     return NOERROR;
}


// ReloadDeskLrcFile
//
// ILrcShowFilter method
// Reload lrc file for desktop mode 
STDMETHODIMP CLrcShowFilter::ReloadDeskLrcFile(const TCHAR * FullPath)
{
     CAutoLock locker(&m_FilterLock);

     LoadDeskLrcFileHelper(FullPath, true);

     return NOERROR;
}

// ReloadWinLrcFile
//
// ILrcShowFilter method
// Reload lrc file for window mode 
STDMETHODIMP CLrcShowFilter::ReloadWinLrcFile(const TCHAR * FullPath)
{
     CAutoLock locker(&m_FilterLock);

     LoadWinLrcFileHelper(FullPath, true);

     return NOERROR;
}

// LoadWinLrcFileHelper & LoadDeskLrcFileHelper
//
// CLrcShowFilter helper method
// Reload lrc file for window & desktop mode
void CLrcShowFilter::LoadWinLrcFileHelper(const TCHAR * FullPath, bool Force)
{
     if( FullPath )
     {
         // Analyze the associated lrc file                              
         m_LrcParser.AnalyzeLrcFile(FullPath, Force);
         // Set the new buffer
         m_WinShower.ChangeMainLrcBuf(m_LrcParser);
     }
}

void CLrcShowFilter::LoadDeskLrcFileHelper(const TCHAR * FullPath, bool Force)
{
     if( FullPath )
     {
         // Analyze the associated lrc file                              
         m_LrcParser.AnalyzeLrcFile(FullPath, Force);
         // Set the new buffer
         m_DesktopShower.ChangeMainLrcBuf(m_LrcParser.GetLrcBuf());
     }
}

//-----------------------------------------------------------------------------
//                  ISpecifyPropertyPages implementation
//-----------------------------------------------------------------------------

// GetPages
//
// Returns the clsid's of the property pages we support
STDMETHODIMP CLrcShowFilter::GetPages(CAUUID *pPages) 
{
     CheckPointer(pPages,E_POINTER);

     pPages->cElems = 3;
     pPages->pElems = (GUID *) CoTaskMemAlloc(sizeof(GUID)*pPages->cElems);

     if( pPages->pElems == NULL )
         return E_OUTOFMEMORY;

     // Three property setting pages
     *(pPages->pElems)   = CLSID_LrcShowFilterWinSettingPage;
     *(pPages->pElems+1) = CLSID_LrcShowFilterDesktopSettingPage;
     *(pPages->pElems+2) = CLSID_LrcOnLineSearchSettingPage;

     return NOERROR;
} 


////////////////////////////////////////////////////////////////////////
//
// Exported entry points for registration and unregistration 
// (in this case they only call through to default implementations).
//
////////////////////////////////////////////////////////////////////////

STDAPI DllRegisterServer()
{
     return AMovieDllRegisterServer2( TRUE );
}

STDAPI DllUnregisterServer()
{
     return AMovieDllRegisterServer2( FALSE );
}